package org.loong.crypto.extension.operator.jce;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;

import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.operator.ContentSigner;
import org.loong.crypto.common.exception.CryptoException;
import org.loong.crypto.core.algorithm.SignatureAlgorithm;
import org.loong.crypto.core.params.SignatureParameters;
import org.loong.crypto.service.CryptoService;

public class JceContentSignerBuilder {

    private CryptoService cryptoService;

    private String signatureAlgorithm;
    
    public JceContentSignerBuilder(CryptoService cryptoService, String signatureAlgorithm) {
        this.cryptoService = cryptoService;
        this.signatureAlgorithm = signatureAlgorithm;
    }
    
    /**
     * Builder an X.509 certificate signer.
     * 
     * @param privateKey privateKey {@link PrivateKey}
     * @return {@link ContentSigner}
     * @throws NoSuchAlgorithmException {@link NoSuchAlgorithmException}
     * @throws CryptoException {@link CryptoException}
     */
    public ContentSigner build(PrivateKey privateKey) throws NoSuchAlgorithmException, CryptoException {
        final SignatureAlgorithm algorithm = SignatureAlgorithm.find(signatureAlgorithm);
        final AlgorithmIdentifier sigAlgId = algorithm.getSigAlgId();
        
        SignatureParameters params = SignatureParameters.builder().key(privateKey).build();
        
        return new ContentSigner() {

            private ByteArrayOutputStream stream = new ByteArrayOutputStream();

            public AlgorithmIdentifier getAlgorithmIdentifier() {
                return sigAlgId;
            }

            public OutputStream getOutputStream() {
                return stream;
            }

            public byte[] getSignature() {
                final byte[] data = stream.toByteArray();
                return cryptoService.sign(algorithm, params, data);
            }
        };
    }
}
